﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Deeper.Common;
namespace Deeper.DataAccess
{
	[Serializable]
	public class Table
	{
		/// <summary>
		/// 表名
		/// </summary>
		public string TableName { private set; get; }
		/// <summary>
		/// 别名
		/// </summary>
		public string AliasName { set; get; }
	}


	[Serializable]
	public class Field
	{
		/// <summary>
		/// 字段*
		/// </summary>
		public static readonly Field All = new Field("ALL", "", "*");
		public string PropertyName { private set; get; }
		private string aliasName;

		#region 内联字段

		internal string FullName
		{
			get
			{
				if (aliasName == null)
					return this.Name;
				return this.Name + " as " + aliasName;
			}
		}

		/// <summary>
		/// 获取真实字段名
		/// </summary>
		public virtual string Name
		{
			get
			{
				if (aliasName != null)
					return aliasName;
				return FieldName;
			}
		}

		/// <summary>
		/// 获取原始的字段名
		/// </summary>
		public string OriginalName
		{
			get
			{

				if (TableName == null)
					return FieldName;
				return TableName + "." + FieldName;
			}
		}



		#region 私有成员

		public string TableName { private set; get; }

		public string FieldName { private set; get; }

		#endregion

		#endregion

		/// <summary>
		/// 实例化Field
		/// </summary>
		/// <param name="fieldName"></param>
		public Field(string fieldName)
		{
			this.PropertyName = fieldName;
			this.FieldName = fieldName;
		}

		/// <summary>
		/// 实例化Field
		/// </summary>
		/// <param name="tableName"></param>
		/// <param name="fieldName"></param>
		public Field(string tableName, string fieldName)
			: this(fieldName)
		{
			this.TableName = string.IsNullOrEmpty(tableName) ? null : tableName;
		}

		/// <summary>
		/// 实例化Field
		/// </summary>
		/// <param name="propertyName"></param>
		/// <param name="tableName"></param>
		/// <param name="fieldName"></param>
		public Field(string propertyName, string tableName, string fieldName)
			: this(tableName, fieldName)
		{
			this.PropertyName = propertyName;
		}

		/// <summary>
		/// 实例化Field
		/// </summary>
		/// <param name="propertyName"></param>
		/// <param name="tableName"></param>
		/// <param name="fieldName"></param>
		/// <param name="aliasName"></param>
		internal Field(string propertyName, string tableName, string fieldName, string aliasName)
			: this(propertyName, tableName, fieldName)
		{
			this.aliasName = string.IsNullOrEmpty(aliasName) ? null : aliasName;
		}

		public override bool Equals(object obj)
		{
			return base.Equals(obj);
		}

		public override int GetHashCode()
		{
			return base.GetHashCode();
		}

		#region 排序操作

		public OrderByClip Asc
		{
			get
			{
				return new OrderByClip(this.Name + " asc ");
			}
		}

		public OrderByClip Desc
		{
			get
			{
				return new OrderByClip(this.Name + " desc ");
			}
		}

		public GroupByClip Group
		{
			get
			{
				return new GroupByClip(this.Name);
			}
		}

		#endregion

		#region 返回条件

		#region 操作符重载

		public static WhereClip operator ==(Field leftField, Field rightField)
		{
			if (leftField.IsNull()) return null;
			if (rightField.IsNull()) return null;
			return new WhereClip(leftField.Name + " = " + rightField.Name);
		}

		public static WhereClip operator !=(Field leftField, Field rightField)
		{
			if (leftField.IsNull()) return null;
			if (rightField.IsNull()) return null;
			return new WhereClip(leftField.Name + " <> " + rightField.Name);
		}

		public static WhereClip operator >(Field leftField, Field rightField)
		{
			if (leftField.IsNull()) return null;
			if (rightField.IsNull()) return null;
			return new WhereClip(leftField.Name + " > " + rightField.Name);
		}

		public static WhereClip operator >=(Field leftField, Field rightField)
		{
			if (leftField.IsNull()) return null;
			if (rightField.IsNull()) return null;
			return new WhereClip(leftField.Name + " >= " + rightField.Name);
		}

		public static WhereClip operator <(Field leftField, Field rightField)
		{
			if (leftField.IsNull()) return null;
			if (rightField.IsNull()) return null;
			return new WhereClip(leftField.Name + " < " + rightField.Name);
		}

		public static WhereClip operator <=(Field leftField, Field rightField)
		{
			if (leftField.IsNull()) return null;
			if (rightField.IsNull()) return null;
			return new WhereClip(leftField.Name + " <= " + rightField.Name);
		}

		public static WhereClip operator ==(Field field, object value)
		{
			if (field.IsNull()) return null;

			return CreateWhereClip(field, "=", value);
		}

		public static WhereClip operator !=(Field field, object value)
		{
			if (field.IsNull()) return null;
			return CreateWhereClip(field, "<>", value);
		}

		public static WhereClip operator >(Field field, object value)
		{
			if (field.IsNull()) return null;
			return CreateWhereClip(field, ">", value);
		}

		public static WhereClip operator >=(Field field, object value)
		{
			if (field.IsNull()) return null;
			return CreateWhereClip(field, ">=", value);
		}

		public static WhereClip operator <(Field field, object value)
		{
			if (field.IsNull()) return null;
			return CreateWhereClip(field, "<", value);
		}

		public static WhereClip operator <=(Field field, object value)
		{
			if (field.IsNull()) return null;
			return CreateWhereClip(field, "<=", value);
		}

		#endregion

		#region 返回字段

		#region 操作符重载

		public static Field operator !(Field field)
		{
			if (field.IsNull()) return null;
			return new Field("~" + field.Name).As(field.OriginalName);
		}

		public static Field operator +(Field leftField, Field rightField)
		{
			if (leftField.IsNull()) return null;
			if (rightField.IsNull()) return null;
			return new Field(leftField.Name + " + " + rightField.Name).As(leftField.OriginalName);
		}

		public static Field operator -(Field leftField, Field rightField)
		{
			if (leftField.IsNull()) return null;
			if (rightField.IsNull()) return null;

			return new Field(leftField.Name + " - " + rightField.Name).As(leftField.OriginalName);
		}

		public static Field operator *(Field leftField, Field rightField)
		{
			if (leftField.IsNull()) return null;
			if (rightField.IsNull()) return null;

			return new Field(leftField.Name + " * " + rightField.Name).As(leftField.OriginalName);
		}

		public static Field operator /(Field leftField, Field rightField)
		{
			if (leftField.IsNull()) return null;
			if (rightField.IsNull()) return null;

			return new Field(leftField.Name + " / " + rightField.Name).As(leftField.OriginalName);
		}

		public static Field operator %(Field leftField, Field rightField)
		{
			if (leftField.IsNull()) return null;
			if (rightField.IsNull()) return null;

			return new Field(leftField.Name + " % " + rightField.Name).As(leftField.OriginalName);
		}

		public static Field operator +(Field field, object value)
		{
			if (field.IsNull()) return null;


			return new Field(field.Name + " + " + value.FormatValue()).As(field.OriginalName);
		}

		public static Field operator -(Field field, object value)
		{
			if (field.IsNull()) return null;
			return new Field(field.Name + " - " + value.FormatValue()).As(field.OriginalName);
		}

		public static Field operator *(Field field, object value)
		{
			if (field.IsNull()) return null;
			return new Field(field.Name + " * " + value.FormatValue()).As(field.OriginalName);
		}

		public static Field operator /(Field field, object value)
		{
			if (field.IsNull()) return null;
			return new Field(field.Name + " / " + value.FormatValue()).As(field.OriginalName);
		}

		public static Field operator %(Field field, object value)
		{
			if (field.IsNull()) return null;
			return new Field(field.Name + " % " + value.FormatValue()).As(field.OriginalName);
		}

		public static Field operator +(object value, Field field)
		{
			if (field.IsNull()) return null;
			return new Field(value.FormatValue() + " + " + field.Name).As(field.OriginalName);
		}

		public static Field operator -(object value, Field field)
		{
			if (field.IsNull()) return null;
			return new Field(value.FormatValue() + " - " + field.Name).As(field.OriginalName);
		}

		public static Field operator *(object value, Field field)
		{
			if (field.IsNull()) return null;
			return new Field(value.FormatValue() + " * " + field.Name).As(field.OriginalName);
		}

		public static Field operator /(object value, Field field)
		{
			if (field.IsNull()) return null;
			return new Field(value.FormatValue() + " / " + field.Name).As(field.OriginalName);
		}

		public static Field operator %(object value, Field field)
		{
			if (field.IsNull()) return null;
			return new Field(value.FormatValue() + " % " + field.Name).As(field.OriginalName);
		}

		#endregion

		#region 字段操作

		/// <summary>
		/// 返回一个值为null的条件
		/// </summary>
		/// <returns></returns>
		public WhereClip IsNullValue()
		{
			return this == (object)null;
		}

		/// <summary>
		/// 判断字段是否为Null
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public Field IsNullValue(Field field)
		{
			return new Field("isnull(" + this.Name + "," + field.Name + ")").As(this.OriginalName);
		}

		/// <summary>
		/// 判断字段是否为Null
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public Field IsNullValue(object value)
		{
			return new Field("isnull(" + this.Name + "," + value.FormatValue() + ")").As(this.OriginalName);
		}

		public Field Distinct()
		{
			return new Field("distinct(" + this.Name + ")");
		}

		public Field Count()
		{
			return new Field("count(" + this.Name + ")").As(this.OriginalName);
		}

		public Field Sum()
		{
			return new Field("sum(" + this.Name + ")").As(this.OriginalName);
		}

		public Field Avg()
		{
			return new Field("avg(" + this.Name + ")").As(this.OriginalName);
		}

		public Field Len()
		{
			return new Field("len(" + this.Name + ")").As(this.OriginalName);
		}

		public Field Trim()
		{
			return new Field("ltrim(rtrim(" + this.Name + "))").As(this.OriginalName);
		}

		public Field Replace(object oldValue, object newValue)
		{
			return new Field("replace(" + this.Name + "," + oldValue.FormatValue() + "," + newValue.FormatValue() + ")").As(this.OriginalName);
		}

		public Field Max()
		{
			return new Field("max(" + this.Name + ")").As(this.OriginalName);
		}

		public Field Min()
		{
			return new Field("min(" + this.Name + ")").As(this.OriginalName);
		}

		public Field Left(int length)
		{
			return new Field("left(" + this.Name + "," + length.ToString() + ")").As(this.OriginalName);
		}

		public Field Right(int length)
		{
			return new Field("right(" + this.Name + "," + length.ToString() + ")").As(this.OriginalName);
		}

		public Field Substring(int startIndex, int endIndex)
		{
			return new Field("substring(" + this.Name + "," + startIndex.ToString() + "," + endIndex.ToString() + ")").As(this.OriginalName);
		}

		public Field IndexOf(string subString)
		{
			return new Field("charindex(" + this.Name + "," + subString + ") - 1").As(this.OriginalName);
		}

		public Field As(string aliasName)
		{
			return new Field(this.PropertyName, this.TableName, this.FieldName, aliasName);
		}

		public Field At(string tableName)
		{
			return new Field(this.PropertyName, TableName, this.FieldName);
		}

		public Field Year
		{
			get
			{
				return new Field("datepart(year," + this.Name + ")").As(this.OriginalName);
			}
		}

		public Field Month
		{
			get
			{
				return new Field("datepart(month," + this.Name + ")").As(this.OriginalName);
			}
		}

		public Field Day
		{
			get
			{
				return new Field("datepart(day," + this.Name + ")").As(this.OriginalName);
			}
		}

		#endregion

		#endregion

		/// <summary>
		/// 指定value进行模糊查询
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public WhereClip Contains(string value)
		{
			return Like("%" + value + "%");
		}

		/// <summary>
		/// 指定value进行Like查询
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public WhereClip Like(string value)
		{
			return CreateWhereClip(this, "like", value);
		}

		/// <summary>
		/// 进行Between操作
		/// </summary>
		/// <param name="leftValue"></param>
		/// <param name="rightValue"></param>
		/// <returns></returns>
		public WhereClip Between(object leftValue, object rightValue)
		{
			return this >= leftValue && this <= rightValue;
		}

		/// <summary>
		/// 返回单字段的bool操作，用于SQLite
		/// </summary>
		public WhereClip IsTrue()
		{
			return new WhereClip(this.Name);
		}
		#endregion

		#region 私有方法

		/// <summary>
		/// 创建一个参数方式的WhereClip
		/// </summary>
		/// <param name="field"></param>
		/// <param name="join"></param>
		/// <param name="value"></param>
		/// <returns></returns>
		private static WhereClip CreateWhereClip(Field field, string join, object value)
		{
			if (value == null)
			{
				if (join == "=")
					return new WhereClip(field.Name + " is null");
				else if (join == "<>")
					return new WhereClip(field.Name + " is not null");
				else
					throw new HDbException("当值为null时只能应用于=与<>操作！");
			}
			if (!(value.GetType().IsPrimitive) && value.GetType().Name != "String" && value.GetType().Name != "Enum")
			{
				throw new HDbException("参数必须是基础数据类型或枚举！");
			}
			string pName = DataHelper.MakeUniqueKey(5, "@");
			MyDbParams p = new MyDbParams(pName, value);

			string where = string.Format("{0} {1} {2}", field.Name, join, p.ParameterName);

			return new WhereClip(where, p);
		}

		#endregion
	}

}
